// 简单粗暴--多线程
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include "InetAddr.hpp"
#include <functional>

using namespace std;

class RouteMessage;
class RouteData
{
public:
    RouteData(RouteMessage *self, int sockfd, const string &message)
    :_self(self),_sockfd(sockfd),_message(message)
    {}
    ~RouteData()
    {}
int _sockfd;
string _message;
RouteMessage *_self;
};

class RouteMessage
{
public:
    RouteMessage()
    {
        pthread_mutex_init(&_mutex, nullptr);
    }

    bool IsExist(const InetAddr &addr)
    {
        for(auto &a:_online_user)
        {
            if(a == addr)
            {
                return true;
            }
        }
        return false;
    }

    void AddUser(const InetAddr &addr)
    {
        pthread_mutex_lock(&_mutex);
        if(!IsExist(addr))
        {
            _online_user.push_back(addr);
        }
        pthread_mutex_unlock(&_mutex);
    }

    void DelUser(const InetAddr &addr)
    {
        pthread_mutex_lock(&_mutex);
        if(!IsExist(addr)) return;
        for(auto iter=_online_user.begin(); iter<_online_user.end(); iter++)
        {
            if(*iter == addr)
            {
                _online_user.erase(iter);
                break;
            }
        }
        pthread_mutex_unlock(&_mutex);
    }

    void RouteHelper(int sockfd, const string &message)
    {
        pthread_mutex_lock(&_mutex);
        for(auto &a:_online_user)
        {
            string str = message + "\n";
            
            struct sockaddr_in clientaddr = a.getAddr();
            sendto(sockfd, str.c_str(), str.size(), 0, (struct sockaddr*)&clientaddr, sizeof(clientaddr));
        }
        pthread_mutex_unlock(&_mutex);
    } 

    static void *HandlerTask(void *args)
    {
        RouteData *rd = static_cast<RouteData *>(args);
        rd->_self->RouteHelper(rd->_sockfd, rd->_message);
        delete rd;
        return nullptr;
    }

    void Route(int sockfd, const string &message, InetAddr addr)
    {
        AddUser(addr);
        if(message == "quit")
        {
            DelUser(addr);
        }

        RouteData *rd = new RouteData(this, sockfd, message);
        pthread_t tid;
        pthread_create(&tid, nullptr, HandlerTask, rd);
    }

    ~RouteMessage()
    {
        pthread_mutex_destroy(&_mutex);
    }

private:    
    pthread_mutex_t _mutex;
    vector<InetAddr> _online_user;
};



// 线程池-未封装原生接口(即没有Thread.hpp)

// #pragma once
// #include <iostream>
// #include <string>
// #include <vector>
// #include "InetAddr.hpp"
// #include "ThreadPool.hpp"
// #include <functional>

// using namespace std;
// using task_t = function<void()>;

// class RouteMessage;
// void Excute(int sockfd, const string &message);
// class RouteData
// {
// public:
//     RouteData(RouteMessage *self, int sockfd, const string &message)
//     :_self(self),_sockfd(sockfd),_message(message)
//     {}
//     void operator()()
//     {
//         Excute(_sockfd, _message);
//     }
//     ~RouteData()
//     {}
// int _sockfd;
// string _message;
// RouteMessage *_self;
// };

// class RouteMessage
// {
// public:
//     RouteMessage()
//     {
//         pthread_mutex_init(&_mutex, nullptr);
//     }

//     bool IsExist(const InetAddr &addr)
//     {
//         for(auto &a:_online_user)
//         {
//             if(a == addr)
//             {
//                 return true;
//             }
//         }
//         return false;
//     }

//     void AddUser(const InetAddr &addr)
//     {
//         pthread_mutex_lock(&_mutex);
//         if(!IsExist(addr))
//         {
//             _online_user.push_back(addr);
//         }
//         pthread_mutex_unlock(&_mutex);
//     }

//     void DelUser(const InetAddr &addr)
//     {
//         pthread_mutex_lock(&_mutex);
//         if(!IsExist(addr)) return;
//         for(auto iter=_online_user.begin(); iter<_online_user.end(); iter++)
//         {
//             if(*iter == addr)
//             {
//                 _online_user.erase(iter);
//                 break;
//             }
//         }
//         pthread_mutex_unlock(&_mutex);
//     }

//     void RouteHelper(int sockfd, const string &message)
//     {
//         pthread_mutex_lock(&_mutex);
//         for(auto &a:_online_user)
//         {
//             cout << message << endl;
//             struct sockaddr_in clientaddr = a.getAddr();
//             sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr*)&clientaddr, sizeof(clientaddr));
//         }
//         pthread_mutex_unlock(&_mutex);
//     } 

//     void Route(int sockfd, const string &message, InetAddr addr)
//     {
//         AddUser(addr);
//         if(message == "quit")
//         {
//             DelUser(addr);
//         }

//         RouteData *rd = new RouteData(this, sockfd, message);
//         ThreadPool<RouteData> *tp = new ThreadPool<RouteData>();
//         tp->InitStart();
//         tp->Enqueue(*rd);
//     }

//     ~RouteMessage()
//     {
//         pthread_mutex_destroy(&_mutex);
//     }

// private:    
//     pthread_mutex_t _mutex;
//     vector<InetAddr> _online_user;
// };

// void Excute(int sockfd, const string &message)
// {
//     RouteMessage roum;
//     roum.RouteHelper(sockfd, message);
// }